home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / stevi69s.zip / EDIT.C < prev    next >
Text File  |  1990-04-23  |  7KB  |  362 lines

  1. /* $Header: /nw/tony/src/stevie/src/RCS/edit.c,v 1.11 89/08/02 19:57:12 tony Exp $
  2.  *
  3.  * The main edit loop as well as some other simple cursor movement routines.
  4.  */
  5.  
  6. #include "stevie.h"
  7.  
  8. /*
  9.  * This flag is used to make auto-indent work right on lines where only
  10.  * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  11.  * and reset when any other editting is done on the line. If an <ESC>
  12.  * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
  13.  */
  14. bool_t    did_ai = FALSE;
  15.  
  16. void
  17. edit()
  18. {
  19.     extern    bool_t    need_redraw;
  20.     int    c;
  21.     register char    *p, *q;
  22.  
  23.     Prenum = 0;
  24.  
  25.     /* position the display and the cursor at the top of the file. */
  26.     *Topchar = *Filemem;
  27.     *Curschar = *Filemem;
  28.     Cursrow = Curscol = 0;
  29.  
  30.     do_mlines();        /* check for mode lines before starting */
  31.  
  32.     updatescreen();
  33.  
  34.     for ( ;; ) {
  35.  
  36.     /* Figure out where the cursor is based on Curschar. */
  37.     cursupdate();
  38.  
  39.     if (need_redraw && !anyinput()) {
  40.         updatescreen();
  41.         need_redraw = FALSE;
  42.     }
  43.  
  44.     if (!anyinput())
  45.         windgoto(Cursrow,Curscol);
  46.  
  47.  
  48.     c = vgetc();
  49.  
  50.     if (State == NORMAL) {
  51.  
  52.         /* We're in the normal (non-insert) mode. */
  53.  
  54.         /* Pick up any leading digits and compute 'Prenum' */
  55.         if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
  56.             Prenum = Prenum*10 + (c-'0');
  57.             continue;
  58.         }
  59.         /* execute the command */
  60.         normal(c);
  61.         Prenum = 0;
  62.  
  63.     } else {
  64.  
  65.         /*
  66.          * Insert or Replace mode.
  67.          */
  68.         switch (c) {
  69.  
  70.         case ESC:    /* an escape ends input mode */
  71.  
  72.             /*
  73.              * If we just did an auto-indent, truncate the
  74.              * line, and put the cursor back.
  75.              */
  76.             if (did_ai) {
  77.                 Curschar->linep->s[0] = NUL;
  78.                 Curschar->index = 0;
  79.                 did_ai = FALSE;
  80.             }
  81.  
  82.             set_want_col = TRUE;
  83.  
  84.             /* Don't end up on a '\n' if you can help it. */
  85.             if (gchar(Curschar) == NUL && Curschar->index != 0)
  86.                 dec(Curschar);
  87.  
  88.             /*
  89.              * The cursor should end up on the last inserted
  90.              * character. This is an attempt to match the real
  91.              * 'vi', but it may not be quite right yet.
  92.              */
  93.             if (Curschar->index != 0 && !endofline(Curschar))
  94.                 dec(Curschar);
  95.  
  96.             State = NORMAL;
  97.             msg("");
  98.  
  99.             /* construct the Redo buffer */
  100.             p=Redobuff;
  101.             q=Insbuff;
  102.             while ( q < Insptr )
  103.                 *p++ = *q++;
  104.             *p++ = ESC;
  105.             *p = NUL;
  106.             updatescreen();
  107.             break;
  108.  
  109.         case CTRL('D'):
  110.             /*
  111.              * Control-D is treated as a backspace in insert
  112.              * mode to make auto-indent easier. This isn't
  113.              * completely compatible with vi, but it's a lot
  114.              * easier than doing it exactly right, and the
  115.              * difference isn't very noticeable.
  116.              */
  117.         case BS:
  118.             /* can't backup past starting point */
  119.             if (Curschar->linep == Insstart->linep &&
  120.                 Curschar->index <= Insstart->index) {
  121.                 beep();
  122.                 break;
  123.             }
  124.  
  125.             /* can't backup to a previous line */
  126.             if (Curschar->linep != Insstart->linep &&
  127.                 Curschar->index <= 0) {
  128.                 beep();
  129.                 break;
  130.             }
  131.  
  132.             did_ai = FALSE;
  133.             dec(Curschar);
  134.             if (State == INSERT)
  135.                 delchar(TRUE);
  136.             /*
  137.              * It's a little strange to put backspaces into
  138.              * the redo buffer, but it makes auto-indent a
  139.              * lot easier to deal with.
  140.              */
  141.             *Insptr++ = BS;
  142.             Ninsert++;
  143.             cursupdate();
  144.             updateline();
  145.             break;
  146.  
  147.         case CR:
  148.         case NL:
  149.             if (State == REPLACE)        /* DMT added, 12/89 */
  150.                 delchar(FALSE);
  151.             *Insptr++ = NL;
  152.             Ninsert++;
  153.             opencmd(FORWARD, TRUE);        /* open a new line */
  154.             break;
  155.  
  156.         default:
  157.             did_ai = FALSE;
  158.             insertchar(c);
  159.             break;
  160.         }
  161.     }
  162.     }
  163. }
  164.  
  165. void
  166. insertchar(c)
  167. int    c;
  168. {
  169.     inschar(c);
  170.     *Insptr++ = c;
  171.     Ninsert++;
  172.     /*
  173.      * The following kludge avoids overflowing the statically
  174.      * allocated insert buffer. Just dump the user back into
  175.      * command mode, and print a message.
  176.      */
  177.     if (Insptr+10 >= &Insbuff[1024]) {
  178.         stuffin(mkstr(ESC));
  179.         emsg("No buffer space - returning to command mode");
  180.         sleep(2);
  181.     }
  182.     updateline();
  183. }
  184.  
  185. void
  186. getout()
  187. {
  188.     windgoto(Rows-1,0);
  189.     putchar('\r');
  190.     putchar('\n');
  191.     windexit(0);
  192. }
  193.  
  194. void
  195. scrolldown(nlines)
  196. int    nlines;
  197. {
  198.     register LPTR    *p;
  199.     register int    done = 0;    /* total # of physical lines done */
  200.  
  201.     /* Scroll up 'nlines' lines. */
  202.     while (nlines--) {
  203.         if ((p = prevline(Topchar)) == NULL)
  204.             break;
  205.         done += plines(p);
  206.         *Topchar = *p;
  207.         /*
  208.          * If the cursor is on the bottom line, we need to
  209.          * make sure it gets moved up the appropriate number
  210.          * of lines so it stays on the screen.
  211.          */
  212.         if (Curschar->linep == Botchar->linep->prev) {
  213.             int    i = 0;
  214.             while (i < done) {
  215.                 i += plines(Curschar);
  216.                 *Curschar = *prevline(Curschar);
  217.             }
  218.         }
  219.     }
  220.     s_ins(0, done);
  221. }
  222.  
  223. void
  224. scrollup(nlines)
  225. int    nlines;
  226. {
  227.     register LPTR    *p;
  228.     register int    done = 0;    /* total # of physical lines done */
  229.     register int    pl;        /* # of plines for the current line */
  230.  
  231.     /* Scroll down 'nlines' lines. */
  232.     while (nlines--) {
  233.         pl = plines(Topchar);
  234.         if ((p = nextline(Topchar)) == NULL)
  235.             break;
  236.         done += pl;
  237.         if (Curschar->linep == Topchar->linep)
  238.             *Curschar = *p;
  239.         *Topchar = *p;
  240.  
  241.     }
  242.     s_del(0, done);
  243. }
  244.  
  245. /*
  246.  * oneright
  247.  * oneleft
  248.  * onedown
  249.  * oneup
  250.  *
  251.  * Move one char {right,left,down,up}.  Return TRUE when
  252.  * successful, FALSE when we hit a boundary (of a line, or the file).
  253.  */
  254.  
  255. bool_t
  256. oneright()
  257. {
  258.     set_want_col = TRUE;
  259.  
  260.     switch (inc(Curschar)) {
  261.  
  262.     case 0:
  263.         return TRUE;
  264.  
  265.     case 1:
  266.         dec(Curschar);        /* crossed a line, so back up */
  267.         /* fall through */
  268. /* v1.1
  269.  *    case -1:
  270.  *        return FALSE;
  271.  */
  272.     }
  273.     /*NOTREACHED*/
  274.     return FALSE;        /* v1.1 cut out Turbo C complaints */
  275. }
  276.  
  277. bool_t
  278. oneleft()
  279. {
  280.     set_want_col = TRUE;
  281.  
  282.     switch (dec(Curschar)) {
  283.  
  284.     case 0:
  285.         return TRUE;
  286.  
  287.     case 1:
  288.         inc(Curschar);        /* crossed a line, so back up */
  289.         /* fall through */
  290. /* v1.1
  291.  *    case -1:
  292.  *        return FALSE;
  293.  */
  294.     }
  295.     /*NOTREACHED*/
  296.     return FALSE;        /* v1.1 cut out Turbo C complaints */
  297. }
  298.  
  299. void
  300. beginline(flag)
  301. bool_t    flag;
  302. {
  303.     while ( oneleft() )
  304.         ;
  305.     if (flag) {
  306.         while (isspace(gchar(Curschar)) && oneright())
  307.             ;
  308.     }
  309.     set_want_col = TRUE;
  310. }
  311.  
  312. bool_t
  313. oneup(n)
  314. int    n;
  315. {
  316.     LPTR    p, *np;
  317.     register int    k;
  318.  
  319.     p = *Curschar;
  320.     for ( k=0; k<n; k++ ) {
  321.         /* Look for the previous line */
  322.         if ( (np=prevline(&p)) == NULL ) {
  323.             /* If we've at least backed up a little .. */
  324.             if ( k > 0 )
  325.                 break;    /* to update the cursor, etc. */
  326.             else
  327.                 return FALSE;
  328.         }
  329.         p = *np;
  330.     }
  331.     *Curschar = p;
  332.     /* This makes sure Topchar gets updated so the complete line */
  333.     /* is one the screen. */
  334.     cursupdate();
  335.     /* try to advance to the column we want to be at */
  336.     *Curschar = *coladvance(&p, Curswant);
  337.     return TRUE;
  338. }
  339.  
  340. bool_t
  341. onedown(n)
  342. int    n;
  343. {
  344.     LPTR    p, *np;
  345.     register int    k;
  346.  
  347.     p = *Curschar;
  348.     for ( k=0; k<n; k++ ) {
  349.         /* Look for the next line */
  350.         if ( (np=nextline(&p)) == NULL ) {
  351.             if ( k > 0 )
  352.                 break;
  353.             else
  354.                 return FALSE;
  355.         }
  356.         p = *np;
  357.     }
  358.     /* try to advance to the column we want to be at */
  359.     *Curschar = *coladvance(&p, Curswant);
  360.     return TRUE;
  361. }
  362.